package org.ne.banksys.controller;

import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.ne.banksys.DTO.UserRegisterDTO;
import org.ne.banksys.common.Result;
import org.ne.banksys.entity.Card;
import org.ne.banksys.entity.User;
import org.ne.banksys.service.BankService;
import org.ne.banksys.service.CardService;
import org.ne.banksys.service.UserService;
import org.ne.banksys.utils.MD5Utils;
import org.ne.banksys.utils.RedisLockUtils;
import org.ne.banksys.utils.ThreadLocalUtils;
import org.ne.banksys.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author wey
 * @date 2025/6/16 上午10:18 06
 **/

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private CardService cardService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


//
//    @PostMapping("/register")
//    public Result register(@RequestBody Map<String, Object> para) {
//        String username = para.get("customerName").toString();
//        String password = para.get("password").toString();
//        String PID = para.get("PID").toString();
//        String phone = para.get("telephone").toString();
//        User u = userService.findByUserPID(PID);
//        if (u == null) {
//            if (userService.findByUserPhone(phone) != null) {
//                return Result.error("phone number already exist");
//            }
//            userService.register(username, password, PID, phone);
//            Map<String, Object> info = new HashMap<>();
//            User user = userService.findByUserPID(PID);
//            info.put("customer", user);
//            info.put("card",cardService.registerCard(user.getCustomerId()) );
//            return Result.success(info);
//        } else {
//            return Result.error("user already exist");
//        }
//    }

    @PostMapping("/register")
    public Result register(@RequestBody @Valid UserRegisterDTO dto, BindingResult result) {
        // 1. 校验失败处理
        if (result.hasErrors()) {
            String errorMsg = Objects.requireNonNull(result.getFieldError()).getDefaultMessage();
            return Result.error(errorMsg);
        }

        // 2. 业务逻辑（原代码逻辑）
        User u = userService.findByUserPID(dto.getPID());
        if (u != null) {
            return Result.error("身份证号已注册");
        }
        if (userService.findByUserPhone(dto.getTelephone()) != null) {
            return Result.error("手机号已存在");
        }
//        userService.register(username, password, PID, phone);
        userService.register(dto.getCustomerName(), dto.getPassword(),dto.getPID(), dto.getTelephone());
        Map<String, Object> info = new HashMap<>();
        User user = userService.findByUserPID(dto.getPID());
        info.put("customer", user);
        info.put("card",cardService.registerCard(user.getCustomerId()) );
        return Result.success(info);
    }


    @PostMapping("/login")
    public Result login(@RequestBody Map<String, Object> para) {
        String username = para.get("customerName").toString();
        String password = para.get("password").toString();
        String md5 = MD5Utils.code(password);
        User user = userService.findByUserName(username);
        if (user == null) {
            return Result.error("user not found");
        }

        if (password.isEmpty()) {
            return Result.error("password is empty");
        }

        if (md5 != null && !md5.equals(user.getPassword())) {
            return Result.error("password error");
        }


        String token = TokenUtils.sign(user);
        Map<String, Object> info = new HashMap<>();
        info.put("user", user);
        info.put("token", token);

        //token -> redis
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        ops.set(token, token, 24, TimeUnit.HOURS);

        return Result.success(info);
    }








    @GetMapping("/detail")
    public Result detail() {

        Map<String, Object> info = ThreadLocalUtils.get();
        System.out.println(info);
        String username = info.get("customerName").toString();

        User user = userService.findByUserName(username);
        System.out.println(user);
        if (user == null) {
            return Result.error("user not found");
        }
        return Result.success(user);
    }


    @PostMapping("/update")
    public Result update(@RequestBody Map<String, Object> para) {

        if (para == null) {
            return Result.error("user not found");
        }

        String PID = para.get("PID").toString();
        String customerName = para.get("customerName").toString();
        String telephone = para.get("telephone").toString();
        String password = para.get("password").toString();


        Map<String, Object> info = ThreadLocalUtils.get();
        Long id = Long.parseLong(info.get("customerId").toString());
        User user = userService.findByUserPID(PID);
        if (user == null) {
            return Result.error("user not found");
        }
        if (!user.getCustomerId().equals(id)) {
            return Result.error("customer id not match");
        }

        if(! user.getPassword().equals( MD5Utils.code(password))) {
            return Result.error("password error");
        }

        user.setCustomerName(customerName);
        user.setTelephone(telephone);
        user.setPID(PID);
        userService.update(user);

        return Result.success(userService.findByUserPID(PID));
    }


    @PostMapping("/addressUpdate")
    public Result addressUpdate(@RequestParam("address") String address) {
        userService.updateAddress(address);
        return Result.success();
    }

    @PostMapping("/pwdUpdate")
    public Result pwdUpdate(@RequestBody @Validated Map<String, Object> para, @RequestHeader("Authorization") String token) {
        String oldPassword = para.get("oldPassword").toString();
        String newPassword = para.get("newPassword").toString();
        String rePassword = para.get("rePassword").toString();
        if (oldPassword == null || newPassword == null || rePassword == null) {
            return Result.error("password format error");
        }

        if (oldPassword.equals(newPassword)) {
            return Result.error("the old password is the same with the new password");
        }

        if (!newPassword.equals(rePassword)) {
            return Result.error("password mismatched");
        }

        String oldMd5 = MD5Utils.code(oldPassword);
        String newMd5 = MD5Utils.code(newPassword);

        Map<String, Object> info = ThreadLocalUtils.get();
        String username = info.get("customerName").toString();
        User logging_user = userService.findByUserName(username);
        if (!logging_user.getPassword().equals(oldMd5)) {
            return Result.error("the old password mismatch");
        }

        userService.updatePwd(newMd5);

        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        ops.getOperations().delete(token);

        return Result.success();
    }

    @DeleteMapping("/delete")
    public Result delete(@RequestBody Map<String, Object> para) {
        String PID = para.get("PID").toString();
        String password = para.get("password").toString();
        String name = para.get("customerName").toString();
        Map<String, Object> info = ThreadLocalUtils.get();

        User user = userService.findByUserPID(PID);
        if (!user.getCustomerId().equals(Long.parseLong((String) info.get("customerId")))) {
            return Result.error("user id mismatch");
        }
        if (Objects.equals(MD5Utils.code(password), user.getPassword()) && Objects.equals(name, user.getCustomerName())) {
            userService.delete(PID, name, password);

            return Result.success();
        }



        return Result.error("PID or password mismatch");

    }


    @Autowired
    private BankService bankService;


    @PostMapping("/withdraw")
    public Result withdraw(@RequestBody Map<String, Object> para) {
        String cardId = para.get("cardId").toString();
        String cardPass = para.get("cardPass").toString();
        String remark = para.get("remark").toString();
        BigDecimal amount = new BigDecimal(para.get("amount").toString());
//        System.out.println(amount);

        String msg= bankService.withdraw(cardId, cardPass, amount,remark);
        return Result.success(msg);
    }

    @PostMapping("/deposit")
    public Result deposit(@RequestBody Map<String, Object> para) {
        String cardId = para.get("cardId").toString();
        String cardPass = para.get("cardPass").toString();
        String remark = para.get("remark").toString();
        BigDecimal amount = new BigDecimal(para.get("amount").toString());

        String msg = bankService.deposit(cardId, cardPass, amount,remark);
        return Result.success(msg);
    }

    @PostMapping("/transfer")
    public Result transfer(@RequestBody Map<String, Object> para) {

        String fromCardId = para.get("fromCardId").toString();
        String toCardId = para.get("toCardId").toString();
        String cardPass = para.get("cardPass").toString();
        String remark = para.get("remark").toString();
        BigDecimal amount = new BigDecimal(para.get("amount").toString());

        
        String msg = bankService.transfer(fromCardId, toCardId, cardPass, amount,remark);
        return Result.success(msg);
    }





}
